package huawei_security_go

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/sha256"
	"errors"
	"golang.org/x/crypto/pbkdf2"
	"strings"
)

type Ciphers struct {
	WorkeyCipher string   `json:"workeyCipher"`
	PasswdCipher string   `json:"passwdCipher"`
	Sysconfig    []string `json:"sysconfig"`
	Config       []string `json:"config"`
}

const (
	defaultHashIteration = 10000
	defaultKeyLen = 16
)

type CipherPart struct {
	rawFullText string
	version string
	transformation string
	ivHex string
	cipherTextHex string
	dynamicSaltHex string
}

func NewCipherPart(rawText string) *CipherPart {
	p := new(CipherPart)
	p.rawFullText = rawText
	p.parseRawText()
	return p
}

func (p *CipherPart) parseRawText() {
	parts := strings.Split(p.rawFullText, "~")
	p.version = parts[0]
	p.transformation = parts[1]
	p.ivHex = parts[2]
	p.cipherTextHex = parts[3]
	p.dynamicSaltHex = ""
}

func genKeyPBKDFSha256(secretKeyHex string, salt []byte) []byte {
	shaKeyRaw := StringCharCode2Byte(secretKeyHex)
	// AES-256: key len: 32
	shaKey := pbkdf2.Key(shaKeyRaw, salt, defaultHashIteration, defaultKeyLen, sha256.New)

	return shaKey
}

func Decrypt(cipherTextHex string, ivHex string, secretKeyHex string, salt []byte) (string, error) {
	sha256Key := genKeyPBKDFSha256(secretKeyHex, salt)

	cipherBlock, err := aes.NewCipher(sha256Key)
	if err != nil {
		return "", errors.New("generate AES cipher failed: " + err.Error())
	}

	iv, err := HexString2Bytes(ivHex)
	cipherText, err := HexString2Bytes(cipherTextHex)

	aesGcm, err := cipher.NewGCM(cipherBlock)
	if err != nil {
		return "", errors.New("generate GCM cipher failed: " + err.Error())
	}

	resBytes, err := aesGcm.Open(nil, iv, cipherText, nil)
	// golang default is utf-8
	return Byte2UTF8String(resBytes), err
}
